From c214c9a95255abf1032d389d0fe8bcbde38b55db Mon Sep 17 00:00:00 2001 From: Reedy Date: Sat, 1 Oct 2016 18:00:53 +0100 Subject: [PATCH] Detect/use APCu properly In PHP 5.5 and above, userland APC caching moved to an extension Bug: T140587 Change-Id: Ie0871776cd7e67838471a4fe95451cf4164079b7 --- autoload.php | 1 + includes/DefaultSettings.php | 3 +- includes/installer/Installer.php | 1 + includes/installer/i18n/en.json | 3 +- includes/installer/i18n/qqq.json | 1 + includes/libs/MemoizedCallable.php | 12 ++- includes/libs/objectcache/APCBagOStuff.php | 32 ++++--- includes/libs/objectcache/APCUBagOStuff.php | 91 +++++++++++++++++++ includes/objectcache/ObjectCache.php | 6 +- .../includes/libs/MemoizedCallableTest.php | 4 +- 10 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 includes/libs/objectcache/APCUBagOStuff.php diff --git a/autoload.php b/autoload.php index e614444aeb..8d9a80fe3b 100644 --- a/autoload.php +++ b/autoload.php @@ -5,6 +5,7 @@ global $wgAutoloadLocalClasses; $wgAutoloadLocalClasses = [ 'APCBagOStuff' => __DIR__ . '/includes/libs/objectcache/APCBagOStuff.php', + 'APCUBagOStuff' => __DIR__ . '/includes/libs/objectcache/APCUBagOStuff.php', 'AbstractContent' => __DIR__ . '/includes/content/AbstractContent.php', 'Action' => __DIR__ . '/includes/actions/Action.php', 'ActiveUsersPager' => __DIR__ . '/includes/specials/pagers/ActiveUsersPager.php', diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index f8626e9da1..b1436b0e94 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2211,7 +2211,7 @@ $wgCacheDirectory = false; * - CACHE_NONE: Do not cache * - CACHE_DB: Store cache objects in the DB * - CACHE_MEMCACHED: MemCached, must specify servers in $wgMemCachedServers - * - CACHE_ACCEL: APC, XCache or WinCache + * - CACHE_ACCEL: APC, APCU, XCache or WinCache * - (other): A string may be used which identifies a cache * configuration in $wgObjectCaches. * @@ -2288,6 +2288,7 @@ $wgObjectCaches = [ ], 'apc' => [ 'class' => 'APCBagOStuff', 'reportDupes' => false ], + 'apcu' => [ 'class' => 'APCUBagOStuff', 'reportDupes' => false ], 'xcache' => [ 'class' => 'XCacheBagOStuff', 'reportDupes' => false ], 'wincache' => [ 'class' => 'WinCacheBagOStuff', 'reportDupes' => false ], 'memcached-php' => [ 'class' => 'MemcachedPhpBagOStuff', 'loggroup' => 'memcached' ], diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php index eafb9d4939..03f997471b 100644 --- a/includes/installer/Installer.php +++ b/includes/installer/Installer.php @@ -244,6 +244,7 @@ abstract class Installer { protected $objectCaches = [ 'xcache' => 'xcache_get', 'apc' => 'apc_fetch', + 'apcu' => 'apcu_fetch', 'wincache' => 'wincache_ucache_get' ]; diff --git a/includes/installer/i18n/en.json b/includes/installer/i18n/en.json index 3f3032b0cf..6a6c0ff28f 100644 --- a/includes/installer/i18n/en.json +++ b/includes/installer/i18n/en.json @@ -57,6 +57,7 @@ "config-memory-bad": "Warning: PHP's memory_limit is $1.\nThis is probably too low.\nThe installation may fail!", "config-xcache": "[http://xcache.lighttpd.net/ XCache] is installed", "config-apc": "[http://www.php.net/apc APC] is installed", + "config-apcu": "[http://www.php.net/apcu APCu] is installed", "config-wincache": "[http://www.iis.net/download/WinCacheForPhp WinCache] is installed", "config-no-cache-apcu": "Warning: Could not find [http://www.php.net/apcu APCu], [http://xcache.lighttpd.net/ XCache] or [http://www.iis.net/download/WinCacheForPhp WinCache].\nObject caching is not enabled.", "config-mod-security": "Warning: Your web server has [http://modsecurity.org/ mod_security]/mod_security2 enabled. Many common configurations of this will cause problems for MediaWiki and other software that allows users to post arbitrary content.\nIf possible, this should be disabled. Otherwise, refer to [http://modsecurity.org/documentation/ mod_security documentation] or contact your host's support if you encounter random errors.", @@ -246,7 +247,7 @@ "config-cache-options": "Settings for object caching:", "config-cache-help": "Object caching is used to improve the speed of MediaWiki by caching frequently used data.\nMedium to large sites are highly encouraged to enable this, and small sites will see benefits as well.", "config-cache-none": "No caching (no functionality is removed, but speed may be impacted on larger wiki sites)", - "config-cache-accel": "PHP object caching (APC, XCache or WinCache)", + "config-cache-accel": "PHP object caching (APC, APCu, XCache or WinCache)", "config-cache-memcached": "Use Memcached (requires additional setup and configuration)", "config-memcached-servers": "Memcached servers:", "config-memcached-help": "List of IP addresses to use for Memcached.\nShould specify one per line and specify the port to be used. For example:\n 127.0.0.1:11211\n 192.168.1.25:1234", diff --git a/includes/installer/i18n/qqq.json b/includes/installer/i18n/qqq.json index 833e7d612a..d7e86bed96 100644 --- a/includes/installer/i18n/qqq.json +++ b/includes/installer/i18n/qqq.json @@ -75,6 +75,7 @@ "config-memory-bad": "Parameters:\n* $1 is the configured memory_limit.", "config-xcache": "Message indicates if this program is available", "config-apc": "Message indicates if this program is available", + "config-apcu": "Message indicates if this program is available", "config-wincache": "Message indicates if this program is available", "config-no-cache-apcu": "Status message in the MediaWiki installer environment checks.", "config-mod-security": "Status message in the MediaWiki installer environment checks.", diff --git a/includes/libs/MemoizedCallable.php b/includes/libs/MemoizedCallable.php index 50e9732b80..12a5cadb99 100644 --- a/includes/libs/MemoizedCallable.php +++ b/includes/libs/MemoizedCallable.php @@ -1,6 +1,6 @@ ttl ); + } elseif ( function_exists( 'apcu_store' ) ) { + apcu_store( $key, $result, $this->ttl ); } } diff --git a/includes/libs/objectcache/APCBagOStuff.php b/includes/libs/objectcache/APCBagOStuff.php index 8f70fc7a77..9bfcee798a 100644 --- a/includes/libs/objectcache/APCBagOStuff.php +++ b/includes/libs/objectcache/APCBagOStuff.php @@ -75,25 +75,35 @@ class APCBagOStuff extends BagOStuff { } protected function doGet( $key, $flags = 0 ) { - $val = apc_fetch( $key . self::KEY_SUFFIX ); + return $this->getUnserialize( + apc_fetch( $key . self::KEY_SUFFIX ) + ); + } - if ( is_string( $val ) && !$this->nativeSerialize ) { - $val = $this->isInteger( $val ) - ? intval( $val ) - : unserialize( $val ); + protected function getUnserialize( $value ) { + if ( is_string( $value ) && !$this->nativeSerialize ) { + $value = $this->isInteger( $value ) + ? intval( $value ) + : unserialize( $value ); } - - return $val; + return $value; } public function set( $key, $value, $exptime = 0, $flags = 0 ) { + apc_store( + $key . self::KEY_SUFFIX, + $this->setSerialize( $value ), + $exptime + ); + + return true; + } + + protected function setSerialize( $value ) { if ( !$this->nativeSerialize && !$this->isInteger( $value ) ) { $value = serialize( $value ); } - - apc_store( $key . self::KEY_SUFFIX, $value, $exptime ); - - return true; + return $value; } public function delete( $key ) { diff --git a/includes/libs/objectcache/APCUBagOStuff.php b/includes/libs/objectcache/APCUBagOStuff.php new file mode 100644 index 0000000000..02b3c928ed --- /dev/null +++ b/includes/libs/objectcache/APCUBagOStuff.php @@ -0,0 +1,91 @@ +getUnserialize( + apcu_fetch( $key . self::KEY_SUFFIX ) + ); + } + + public function set( $key, $value, $exptime = 0, $flags = 0 ) { + apcu_store( + $key . self::KEY_SUFFIX, + $this->setSerialize( $value ), + $exptime + ); + + return true; + } + + public function delete( $key ) { + apcu_delete( $key . self::KEY_SUFFIX ); + + return true; + } + + public function incr( $key, $value = 1 ) { + /** + * @todo When we only support php 7 or higher remove this hack + * + * https://github.com/krakjoe/apcu/issues/166 + */ + if ( apcu_exists( $key . self::KEY_SUFFIX ) ) { + return apcu_inc( $key . self::KEY_SUFFIX, $value ); + } else { + return apcu_set( $key . self::KEY_SUFFIX, $value ); + } + } + + public function decr( $key, $value = 1 ) { + /** + * @todo When we only support php 7 or higher remove this hack + * + * https://github.com/krakjoe/apcu/issues/166 + */ + if ( apcu_exists( $key . self::KEY_SUFFIX ) ) { + return apcu_dec( $key . self::KEY_SUFFIX, $value ); + } else { + return apcu_set( $key . self::KEY_SUFFIX, -$value ); + } + } +} diff --git a/includes/objectcache/ObjectCache.php b/includes/objectcache/ObjectCache.php index d81f9e13cb..87a62727fe 100644 --- a/includes/objectcache/ObjectCache.php +++ b/includes/objectcache/ObjectCache.php @@ -50,7 +50,7 @@ use MediaWiki\MediaWikiServices; * * - ObjectCache::getLocalServerInstance( $fallbackType ) * Purpose: Memory cache for very hot keys. - * Stored only on the individual web server (typically APC for web requests, + * Stored only on the individual web server (typically APC or APCu for web requests, * and EmptyBagOStuff in CLI mode). * Not replicated to the other servers. * @@ -265,7 +265,7 @@ class ObjectCache { /** * Factory function for CACHE_ACCEL (referenced from DefaultSettings.php) * - * This will look for any APC style server-local cache. + * This will look for any APC or APCu style server-local cache. * A fallback cache can be specified if none is found. * * // Direct calls @@ -282,6 +282,8 @@ class ObjectCache { public static function getLocalServerInstance( $fallback = CACHE_NONE ) { if ( function_exists( 'apc_fetch' ) ) { $id = 'apc'; + } elseif ( function_exists( 'apcu_fetch' ) ) { + $id = 'apcu'; } elseif ( function_exists( 'xcache_get' ) && wfIniGetBool( 'xcache.var_size' ) ) { $id = 'xcache'; } elseif ( function_exists( 'wincache_ucache_get' ) ) { diff --git a/tests/phpunit/includes/libs/MemoizedCallableTest.php b/tests/phpunit/includes/libs/MemoizedCallableTest.php index 6eb96b157e..881f5e1167 100644 --- a/tests/phpunit/includes/libs/MemoizedCallableTest.php +++ b/tests/phpunit/includes/libs/MemoizedCallableTest.php @@ -1,7 +1,7 @@ getMock( 'stdClass', [ 'computeSomething' ] ); -- 2.20.1